﻿#ifndef _OI_PLSCANNERCORE_PRODUCTPARAMS_HPP_
#define _OI_PLSCANNERCORE_PRODUCTPARAMS_HPP_

#include "PLScannerCore/OiPLScannerCore.hpp"
#include "Settings/OiSettingsDlg.hpp"

namespace Oi { namespace PLScannerCore {


class OI_PLSCANNER_CORE_API DefinitionPoint
{
public:
    int type;
    double distance;
    double thicknessLeft;
    double thicknessRight;
    double radius;

public:
    DefinitionPoint()
    {
        type = 0;
        distance = 0.0;
        thicknessLeft = 0.0;
        thicknessRight = 0.0;
        radius = 0.0;
    }

    DefinitionPoint(const DefinitionPoint& p)
    {
        *this = p;
    }

    DefinitionPoint& operator=(const DefinitionPoint& p)
    {
        type = p.type;
        distance = p.distance;
        thicknessLeft = p.thicknessLeft;
        thicknessRight = p.thicknessRight;
        radius = p.radius;
        return *this;
    }

    bool operator==(const DefinitionPoint &p) const
    {
        if(type != p.type)
        {
            return false;
        }
        if(distance != p.distance)
        {
            return false;
        }
        if(thicknessLeft != p.thicknessLeft)
        {
            return false;
        }
        if(thicknessRight != p.thicknessRight)
        {
            return false;
        }
        if(radius != p.radius)
        {
            return false;
        }
        return true;
    }

    bool operator!=(const DefinitionPoint &p) const
    {
        return !( *this == p );
    }
};

class OI_PLSCANNER_CORE_API ProductParams
{
    
public:
    QString specName;
    int materialsType;
    double materialsWidth;
    double materialsUpWidth;
    double materialsThickness;
    QList<DefinitionPoint> definitionPoints;
    QList<QPointF> measureThickness;
    QPointF fixedPoint;
    OiProfiles profiles;
    QMap<int, QVariant> insParams;
    QVariantMap config;
    int measureType;

public:
    ProductParams();

    ProductParams(const ProductParams& p);

    ProductParams(const int mtype, const QString mSpec, const double mWidth, const double mUpWidth, const double mThickness, const int mMeasureType
        , const QList<DefinitionPoint> mdefinitionPoints = QList<DefinitionPoint>()
        , const QList<QPointF> mmeasureThickness = QList<QPointF>()
        , const QPointF mfixedPoint = QPointF()
        , const OiProfiles mprofiles = OiProfiles()
        , const QMap<int, QVariant> mInsParams = QMap<int, QVariant>());

    ProductParams(const QString mSpec, const double mWidth, const double mUpWidth, const double mThickness, const int mMeasureType
        , const QList<DefinitionPoint> mdefinitionPoints
        , const QList<double> mmeasureThicknessPos 
        , const double mfixedPos
        , const double mWidthErrTol
        , const double mWidthWarnTol
        , const double mThicknessErrTol
        , const double mThicknessWarnTol);

    ProductParams& operator=(const ProductParams& p);

    bool operator==(const ProductParams &p) const;

    bool operator!=(const ProductParams &p) const;

public:
    bool getStdValue(int index, QString key, double& value);
    bool getMeasureEnable(int index, QString key, int& value);
    bool getMeasureWarningTol(int index, QString key, double& value);
    bool getMeasureErrorTol(int index, QString key, double& value);
    void getMeasurePrecision( int& value);
    void getMeasureEdgeThickness(double& thickness);

public:
    static OiProfiles createProfile(double width, const double thickness, const QList<DefinitionPoint> definitionPoints);
    void setDefinitionPoints(const QList<DefinitionPoint> mdefinitionPoints);

public:

    static ProductParams params(int& success);

    static QString current();

    static QString next();

    static void setCurrent(const QString);

    static void setNext(const QString);

    static bool checkName(const QString name);

public:
    static int loadFromJson(const QString file);

    static bool loadFromLocal(ProductParams& params, const QString name, const QString path = QString());
    static bool loadFromSys(ProductParams& params, const QString name);
    static bool loadFromSysAndLocal(ProductParams& params, const QString name);
    static bool loadNameFromSys(QString& spec, const QString name);
    static bool loadFromIni(ProductParams& params);

    static bool saveToLocal(const ProductParams& params, const QString path = QString());
    static bool saveToSys(const ProductParams& params, const QString name);
    static bool saveToIni(const ProductParams& params);

    static void updateParams();
    static void updateFormual();
};

class OI_PLSCANNER_CORE_API ParamsReader
{
public:
    virtual ~ParamsReader() {}

public:
    virtual  bool ready() = 0;

public:
    virtual bool specName(QString&) = 0;
    virtual bool params(ProductParams&) = 0;

public:
    static QSharedPointer<ParamsReader> create(QString name);
};

class OI_PLSCANNER_CORE_API ParamsReaderSystem
{
public:
    ParamsReaderSystem();
    ~ParamsReaderSystem();

public:
    QSharedPointer<ParamsReader> reader(QString name);

public:
    void clear();

public:
    void addReader(QString name, QSharedPointer<ParamsReader>);

public:
    static ParamsReaderSystem* instance();

private:
    OI_DISABLE_COPY(ParamsReaderSystem);
    OI_DECLARE_IMPL(ParamsReaderSystem);
};

OI_PLSCANNER_CORE_API QDataStream &operator << (QDataStream &stream, const DefinitionPoint dp);
OI_PLSCANNER_CORE_API QDataStream &operator >> (QDataStream &stream, DefinitionPoint& dp);

} }



#endif
